/*
 * @Author: intellectual-seeker 3336339701@qq.com
 * @Date: 2025-09-01 09:58:07
 * @LastEditors: intellectual-seeker 3336339701@qq.com
 * @LastEditTime: 2025-09-01 14:34:31
 * @FilePath: /code/lesson32/testThread.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "Thread.hpp"
using namespace ThreadModule;
#include <string>
#include <unistd.h>
#include <vector>
#include "LockGuard.hpp"

//多线程访问未保护共享资源的数据不一致问题
int g_tickets = 10000;

//version 2
class ThreadData
{
public:
    ThreadData(int& tickets, string name, pthread_mutex_t& mutex)
        :_tickets(tickets), _name(name), _mutex(mutex)
    {}

    ~ThreadData()
    {}

public:
    int& _tickets;
    string _name;
    int _totals;
    pthread_mutex_t& _mutex;
};

//version1
// class ThreadData
// {
// public:
//     ThreadData(int& tickets, string name)
//         :_tickets(tickets), _name(name)
//     {}

//     ~ThreadData()
//     {}

// public:
//     int& _tickets;
//     string _name;
//     int _totals;
// };

//数据不一致，互斥解决，加锁
//全局锁
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void routine(ThreadData* td)
{
    while(true)
    {
        //pthread_mutex_lock(&mutex);//1. 全局锁
        //pthread_mutex_lock(&td->_mutex);//2. 局部锁
        //LockGuard lockGuard(&td->_mutex);//3. RAII版本
        if(td->_tickets > 0)
        {
            usleep(1000);
            cout << td->_name << ", get ticket is : " << td->_tickets << endl;
            td->_tickets--;
            //pthread_mutex_unlock(&mutex);//1. 
            //pthread_mutex_unlock(&td->_mutex);//2. 
            td->_totals++;
        }
        else
        {
            //pthread_mutex_unlock(&mutex);//1. 
            //pthread_mutex_unlock(&td->_mutex);//2. 
            break;
        }
    }
}

const int num = 4;

int main()
{
    //局部锁
    //pthread_mutex_t mutex;
    //pthread_mutex_init(&mutex, nullptr);

    vector<Thread<ThreadData*>> threads;
    vector<ThreadData*> tdatas;
    for(int i = 0; i < num; i++)
    {
        string name = "Pthread-" + to_string(i + 1);
        //ThreadData* td = new ThreadData(g_tickets, name, mutex);
        ThreadData* td = new ThreadData(g_tickets, name);
        tdatas.emplace_back(td);
        threads.emplace_back(routine, td, name);
    }

    for(auto& thread : threads)
    {
        thread.start();
    }

    for(auto& thread : threads)
    {
        thread.join();
    }

    for(auto& td : tdatas)
    {
        cout << td->_name << ", get total tickets is : " << td->_totals << endl;
        delete td;
    }

    //pthread_mutex_destroy(&mutex);

    return 0;
}